package top.songxs.yygh.service.order.service.impl;

import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import top.songxs.yygh.enums.PaymentTypeEnum;
import top.songxs.yygh.enums.RefundStatusEnum;
import top.songxs.yygh.model.order.OrderInfo;
import top.songxs.yygh.model.order.PaymentInfo;
import top.songxs.yygh.model.order.RefundInfo;
import top.songxs.yygh.service.order.service.OrderInfoService;
import top.songxs.yygh.service.order.service.PaymentService;
import top.songxs.yygh.service.order.service.RefundService;
import top.songxs.yygh.service.order.service.WeixinService;
import top.songxs.yygh.service.order.util.ConstantPropertiesUtils;
import top.songxs.yygh.service.order.util.HttpClient;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

;

@Service
public class WeixinServiceImpl implements WeixinService {

    @Autowired
    private OrderInfoService orderInfoService;
    @Autowired
    private PaymentService paymentService;
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    RefundService refundService;

    /**
     * 根据订单号下单，生成支付链接
     */
    @Override
    public Map<String, Object> createNative(Long orderId) {

        try {
            //1。先尝试从redis中根据订单id获取到map（支付链接），如果有直接返回
            Map<String, Object> payMap = (Map<String, Object>) redisTemplate.opsForValue().get(orderId.toString());
            if (payMap != null)
                return payMap;
            //2.根据订单id获取订单信息
            OrderInfo orderInfo = orderInfoService.getOrderInfo(orderId.toString());
            //3.根据订单对象创建订单支付记录对象
            paymentService.savePaymentInfo(orderInfo, PaymentTypeEnum.WEIXIN.getStatus());
            //4、调用微信端“交易预创建接口”：封装所需要的参数
            Map<String, String> param = new HashMap<>();
            param.put("appid", ConstantPropertiesUtils.APPID);  //appid
            param.put("mch_id", ConstantPropertiesUtils.PARTNER); //主体户
            param.put("nonce_str", WXPayUtil.generateNonceStr()); // 随机字符串
            Date reserveDate = orderInfo.getReserveDate();
            String reserveDateString = new DateTime(reserveDate).toString("yyyy/MM/dd");
            String body = reserveDateString + "就诊" + orderInfo.getDepname();
            param.put("body", body);
            param.put("out_trade_no", orderInfo.getOutTradeNo());
            param.put("total_fee", "1");//为了测试，支付金额为1分
            //param.put("total_fee",orderInfo.getAmount().multiply(new BigDecimal("100")).longValue()+"");
            param.put("spbill_create_ip", "127.0.0.1");
            //
            param.put("notify_url", "http://guli.shop/api/order/weixinPay/weixinNotify");
            param.put("trade_type", "NATIVE");

            //5、使用httpClient发送http请求
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
            client.setXmlParam(WXPayUtil.generateSignedXml(param, ConstantPropertiesUtils.PARTNERKEY));//商户的key
            client.setHttps(true);
            client.post();
            //6、从微信端拿到返回数据
            String content = client.getContent();
            Map<String, String> resultMap = WXPayUtil.xmlToMap(content);

            //7、 封装返回结果集
            Map<String, Object> map = new HashMap<>();
            map.put("orderId", orderId);
            map.put("totalFee", orderInfo.getAmount());//订单金额
            map.put("resultCode", resultMap.get("result_code"));  //SUCCESS/FAIL
            map.put("codeUrl", resultMap.get("code_url"));   //最终返回的支付链接 需要交给前端进行转换为二维码

            //8、暂存到redis中 
            redisTemplate.opsForValue().set(orderId.toString(), map, 5, TimeUnit.MINUTES);
            return map;
        } catch (Exception e) {
            e.printStackTrace();
            return new HashMap<String, Object>();

        }
    }


    /**
     * 根据订单号去微信第三方查询支付状态
     */
    @Override
    public Map<String, String> queryPayStatus(Long orderId) {
        try {
            OrderInfo orderInfo = orderInfoService.getOrderInfo(orderId.toString());
            //1、封装参数
            Map<String, String> paramMap = new HashMap<>();
            paramMap.put("appid", ConstantPropertiesUtils.APPID);
            paramMap.put("mch_id", ConstantPropertiesUtils.PARTNER); //商体户
            paramMap.put("out_trade_no", orderInfo.getOutTradeNo()); //医院端订单号
            paramMap.put("nonce_str", WXPayUtil.generateNonceStr()); //随机字符串
            //2、设置请求
            String url = "https://api.mch.weixin.qq.com/pay/orderquery";
            HttpClient client = new HttpClient(url);
            client.setHttps(true);
            client.setXmlParam(WXPayUtil.generateSignedXml(paramMap, ConstantPropertiesUtils.PARTNERKEY));
            client.post();
            //3、返回第三方数据，转成map
            String content = client.getContent();
            Map<String, String> resultMap = WXPayUtil.xmlToMap(content);
            return resultMap;


        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }


    }

    @Override
    public Boolean refund(Long orderId) {
        //1、根据订单id查询支付记录
        PaymentInfo paymentInfo = paymentService.getByOrderId(orderId);
        //2、利用支付记录创建退款记录
        RefundInfo refundInfo = refundService.saveRefundInfo(paymentInfo);
        //3、判断退款记录的退款状态如果为已退款则直接return
        Integer refundStatus = refundInfo.getRefundStatus();
        if (refundStatus == RefundStatusEnum.REFUND.getStatus()) return true;
        //4、如果未退款，调用微信退款接口
        Map<String, String> paramMap = new HashMap<>();

        paramMap.put("appid", ConstantPropertiesUtils.APPID);
        paramMap.put("mch_id", ConstantPropertiesUtils.PARTNER);
        paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
        paramMap.put("transaction_id", paymentInfo.getTradeNo());
        paramMap.put("out_trade_no", paymentInfo.getOutTradeNo());
        paramMap.put("out_refund_no", "tk" + paymentInfo.getOutTradeNo()); //商户退款单号
        //paramMap.put("total_fee",paymentInfoQuery.getTotalAmount().multiply(new BigDecimal("100")).longValue()+"");
        //paramMap.put("refund_fee",paymentInfoQuery.getTotalAmount().multiply(new BigDecimal("100")).longValue()+"");
        paramMap.put("total_fee", "1");
        paramMap.put("refund_fee", "1");

        //map转成xml字符串，字符串中使用PARTNERKEY生成签名
        try {
            String paramXml = WXPayUtil.generateSignedXml(paramMap, ConstantPropertiesUtils.PARTNERKEY);
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/secapi/pay/refund");
            client.setXmlParam(paramXml);
            client.setHttps(true);
            client.setCert(true);//是否需要证书
            client.setCertPassword(ConstantPropertiesUtils.PARTNER);//证书密码商户号
            client.post();


            //5、微信端返回值，xml字符串转成map对象
            String content = client.getContent();
            Map<String, String> resultMap = WXPayUtil.xmlToMap(content);
            //6、result_code等于SUCCESS说明退款接口调用成功
            String resultCode = resultMap.get("result_code");
            if (WXPayConstants.SUCCESS.equalsIgnoreCase(resultCode)) {
                //将微信端返回值更新到退款记录中
                //如果退款成功，将退款记录的4个属性重新赋值
                refundInfo.setTradeNo(resultMap.get("refund_id"));//微信退款单号
                refundInfo.setCallbackTime(new Date());//回调时间
                refundInfo.setRefundStatus(RefundStatusEnum.REFUND.getStatus());//退款状态已退款
                refundInfo.setCallbackContent(resultMap.toString());//微信接口返回的map.toString

                refundService.updateById(refundInfo);//更新到数据库中
                return true;//成功
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return false;
    }
}
